﻿
using System.Linq;
using System;
using System.Collections;
using System.Collections.Generic;

namespace PS.DataTypes
{
    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class Graph : IGraph
    {
        #region Fields

        private readonly IConnection[] connections;

        private Edge[,] adjacencyMatrix;

        #endregion

        #region Constructors

        public Graph(IConnection[] connections)
        {
            this.connections = connections;
        }

        public Graph(Vertex[] vertices, Edge[] edges)
        {
            adjacencyMatrix = new Edge[edges.Length, edges.Length];

            foreach (Edge e in edges)
            {
                adjacencyMatrix[e.VertexA.Id, e.VertexB.Id] = e;
                adjacencyMatrix[e.VertexB.Id, e.VertexA.Id] = e;
            }

            this.Vertices = vertices;
            this.Edges = edges;
        }

        #endregion

        #region Properties

        public Vertex[] Vertices { get; private set; }

        public Edge[] Edges { get; private set; }

        #endregion

        #region public Methods

        public IConnection[] Connections(int node)
        {
            var cons = from IConnection c in connections
                       where c.FromNode == node || c.ToNode == node
                       select c;

            return cons.ToArray();
        }

        public IConnection[] Connections()
        {
            return connections;
        }

        public Vertex[] GetAdjacentVertices(Vertex v)
        {
            ArrayList adjacents = new ArrayList();

            for (int i = 0; i < adjacencyMatrix.GetLength(1); i++)
            {
                Edge current = adjacencyMatrix[v.Id, i];
                if (current != null) adjacents.Add(Vertices[i]);
            }

            Vertex[] adjacentsArray = new Vertex[adjacents.Count];
            int j = 0;
            foreach (Vertex a in adjacents)
            {
                adjacentsArray[j++] = a;
            }
            
            return adjacentsArray;
        }

        internal Edge IncidentEdge(Vertex v, Vertex n)
        {
            return adjacencyMatrix[v.Id, n.Id];
        }

        #endregion
    }
}
